package com.ridu.project.beshid.service.impl;

import com.ridu.project.beshid.api.Platform;
import com.ridu.project.beshid.api.GeneralResponse;
import com.ridu.project.beshid.api.Status;
import com.ridu.project.beshid.api.TransactionReceipt;
import com.ridu.project.beshid.config.Global;
import com.ridu.project.beshid.config.GlobalConfiguration;
import com.ridu.project.beshid.entity.PlatformEntity;
import com.ridu.project.beshid.repository.PlatformRepository;
import com.ridu.project.beshid.service.PlatformService;
import com.ridu.project.beshid.utils.DateUtil;
import com.ridu.project.beshid.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

/**
 * Created by user on 2017/10/18.
 */
@Service
@Slf4j
public class PlatformServiceImpl implements PlatformService {

    @Autowired
    private GlobalConfiguration globalConfiguration;
    @Autowired
    private PlatformRepository repository;
    @Autowired
    RestService restService;

    @Override
    public GeneralResponse<Platform> findAll(int currentPage, int pageSize
            , String startTime, String endTime, String accessToken) {
        GeneralResponse<Platform> response = new GeneralResponse<>();
        try {
            if (currentPage == 0) {
                currentPage = 1;
            }
            if (pageSize == 0) {
                pageSize = Global.DEFAULT_PAGE_SIZE;
            }
            Sort sort = new Sort(Sort.Direction.DESC, "id");
            Pageable pageable = new PageRequest(currentPage - 1, pageSize, sort);
            Page<PlatformEntity> page = repository.findAll(new Specification<PlatformEntity>() {
                @Override
                public Predicate toPredicate(Root<PlatformEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    Date s = DateUtil.parse(startTime);
                    Date e = DateUtil.parse(endTime + " 23:59:59");
                    List<Predicate> queryPredicates = new ArrayList<>();
                    if (!StringUtil.format(startTime).equals("") ||
                            !StringUtil.format(endTime).equals("")) {
                        if (!StringUtil.format(startTime).equals("") &&
                                !StringUtil.format(endTime).equals("")) {
                            queryPredicates.add(cb.between(root.<Date>get("dateCreated"), s, e));
                        } else if (StringUtil.format(startTime).equals("")) {
                            queryPredicates.add(cb.lessThanOrEqualTo(root.<Date>get("dateCreated"), e));
                        } else if (StringUtil.format(endTime).equals("")) {
                            queryPredicates.add(cb.greaterThanOrEqualTo(root.<Date>get("dateCreated"), s));
                        }
                    }
                    if(StringUtils.isNotBlank(accessToken)){
                        queryPredicates.add(cb.equal(root.<String>get("accessToken"), accessToken));
                    }
                    query.where(queryPredicates.toArray(new Predicate[0]));
                    return null;
                }
            }, pageable);
            List<PlatformEntity> dataList = page.getContent();
            List<Platform> platforms = new ArrayList<>();
            dataList.stream().forEach(platformEntity -> {
                Platform p = new Platform();
                BeanUtils.copyProperties(platformEntity, p);
                platforms.add(p);
            });
            response.setStatus(Status.SUCCESS);
            response.setRows(platforms);
            response.setTotal(page.getTotalElements());
        } catch (Exception e) {
            response.setStatus(Status.FAILED);
            response.setMessage(e.getMessage());
            log.error("error", e);
        }
        return response;
    }

    @Override
    public GeneralResponse getDetail(String transactionHash) {
        GeneralResponse<TransactionReceipt> response = new GeneralResponse<>();
        Map<String, String> map = new HashMap<>();
        map.put("transactionHash", transactionHash);
        List<TransactionReceipt> trs = new ArrayList<>();
        TransactionReceipt tr = (TransactionReceipt) restService.getForObject(globalConfiguration.getServiceUrl()+"platform/getReceiptForManagement", map, TransactionReceipt.class);
        if(tr != null){
            trs.add(tr);
        }
        response.setStatus(Status.SUCCESS);
        response.setRows(trs);
        response.setTotal(CollectionUtils.size(trs));
        return response;
    }

    @Override
    public GeneralResponse save(String name, String code) {
        GeneralResponse r = new GeneralResponse();
        try{
            if(StringUtil.isEmpty(code)){
                throw new Exception("code is not null");
            }
            PlatformEntity pe = new PlatformEntity();
            pe.setName(name);
            pe.setCode(code);
            repository.save(pe);
            r.setStatus(Status.SUCCESS);
        } catch (Exception e){
            r.setStatus(Status.FAILED);
            r.setMessage(e.getMessage());
            log.error(e.getMessage());
        }
        return r;
    }

    @Override
    public GeneralResponse del(String codes) {
        GeneralResponse r = new GeneralResponse();
        try{
            String[] strs = codes.split(",");
            List<PlatformEntity> list = new ArrayList<>();
            for(String str : strs){
                PlatformEntity pe = repository.findByCode(str);
                if(pe != null){
                    list.add(pe);
                }
            }

            repository.deleteInBatch(list);
            r.setStatus(Status.SUCCESS);
        } catch (Exception e){
            r.setStatus(Status.FAILED);
            r.setMessage(e.getMessage());
            log.error(e.getMessage());
        }
        return r;
    }

}
